﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using SharePhone.Common;
using SharePhone.Common.List;
using SharePhone.Common.Web;
using SharePhone.Core;
using SharePhone.Provider.WebServices;
using SharePhone.Utility;

namespace SharePhone.Provider
{
    public delegate void ListItemsTransferCompleted<T>(BaseItemList<T> items) where T : BaseItem, new();

    public delegate void ListItemsUpdateCompleted(object sender, EventArgs e);

    public class ListItemProvider
    {
        public static void GetListItems<T>(SPWeb parentWeb, SPList<T> list, int rowLimit,
                                           ListItemsTransferCompleted<T> itemsDelegate, XElement query,
                                           CredentialSettings credentials) where T : BaseItem, new()
        {
            if (String.IsNullOrEmpty(parentWeb.Url))
                throw new NullReferenceException(
                    "No web url has been configured for this context, please set the WebUrl property");
            var listQuery = new XElement("Query");
            if (query != null)
                listQuery.Add(query);
            XElement listViewFields = CoreObjectFactory.GenerateCoreObjectViewFields<T>();
            var listQueryOptions = new XElement("QueryOptions", new XElement("IncludeMandatoryColumns", true));
            var client = new SPListService(parentWeb.Url, credentials);
            Guid contextId = Guid.NewGuid();
            client.GetListItemsCompleted += (object sender, RequestCompleteEventArgs e) =>
                                                {
                                                    BaseItemList<T> items =
                                                        CoreObjectFactory.CreateCoreObjectList(e.Result, list);
                                                    items.ParentList = list;
                                                    if (itemsDelegate != null)
                                                        itemsDelegate(items);
                                                };

            client.GetListItemsAsync(list, listQuery, listViewFields, rowLimit, listQueryOptions);
        }

        public static void UpdateListItems<T>(SPList<T> list, XElement batchUpdate, ListItemsUpdateCompleted callBack)
            where T : BaseItem, new()
        {
            var client = new SPListService(list.ParentWeb.Url, list.ParentWeb.Settings.Credentials);
            client.UpdateListItemsCompleted += (object sender, RequestCompleteEventArgs e) =>
                                                   {
                                                       ParseItemResultXML(e.Result, list);
                                                       callBack(list, new EventArgs());
                                                   };
            client.UpdateListItemsAsync(list.Title, batchUpdate);
        }

        private static void ParseItemResultXML<T>(XElement result, SPList<T> list) where T : BaseItem, new()
        {
            IEnumerable<XElement> results = result.Elements();
            foreach (XElement res in results)
            {
                if (
                    res.Descendants(XName.Get("ErrorCode", "http://schemas.microsoft.com/sharepoint/soap/")).First().
                        Value != "0x00000000")
                {
                    throw new BaseCoreException("Error while updating list item");
                }
                string s = XmlUtility.GetAttributeValue(res, "ID");
                int updateId = Int32.Parse(s.Substring(0, s.IndexOf(',')));
                string mode = s.Substring(s.IndexOf(',') + 1).Trim();
                T item = list.Items.Where(i => i.updateId == updateId).FirstOrDefault();
                if (item != null)
                {
                    if (mode == "Update" || mode == "New")
                    {
                        XElement row = res.Element(XmlUtility.Z + "row");
                        item.SPListItemId = Int32.Parse(XmlUtility.GetAttributeValue(row, "ows_ID"));
                        item.UniqueId = new Guid(XmlUtility.GetAttributeValue(row, "ows_GUID"));
                        item.EncodedAbsoluteURL = XmlUtility.GetAttributeValue(row, "ows_EncodedAbsUrl");
                        item.ServerRelativeURL = XmlUtility.GetAttributeValue(row, "ows_ServerUrl");
                        item.IsCurrentVersion = (XmlUtility.GetAttributeValue(row, "ows_IsCurrentVersion") == "1"
                                                     ? true
                                                     : false);
                        item.ModifiedDate = DateTime.Parse(XmlUtility.GetAttributeValue(row, "ows_Modified"));
                        item.Created = DateTime.Parse(XmlUtility.GetAttributeValue(row, "ows_Created"));
                        item.CreatedBy = XmlUtility.GetAttributeValue(row, "ows_Author");
                        item.CreatedBy = item.CreatedBy.Substring(item.CreatedBy.IndexOf(";#") + 2);
                        item.ModifiedBy = XmlUtility.GetAttributeValue(row, "ows_Editor");
                        item.ModifiedBy = item.ModifiedBy.Substring(item.ModifiedBy.IndexOf(";#") + 2);
                        item.FileRef = XmlUtility.GetAttributeValue(row, "ows_FileRef");
                        item.FileRef = item.FileRef.Substring(item.FileRef.IndexOf(";#") + 2);
                        item.FileName = XmlUtility.GetAttributeValue(row, "ows_FileLeafRef");
                        item.FileName = item.FileName.Substring(item.FileName.IndexOf(";#") + 2);
                    }
                    else if (mode == "Delete")
                    {
                        item.State = ItemState.Deleted;
                        list.Items.Remove(item);
                    }
                }
            }
        }
    }
}